package com.joker.demo.core.netty.server.handler;

import com.alibaba.fastjson2.JSON;
import com.joker.demo.core.domain.bo.JobRegistryBO;
import com.joker.demo.core.domain.dto.MessageDTO;
import com.joker.demo.core.domain.dto.TaskCancelResponseDTO;
import com.joker.demo.core.domain.dto.TaskExecuteResponseDTO;
import com.joker.demo.core.domain.dto.ThreadPoolMonitorDTO;
import com.joker.demo.core.domain.dto.EnvironmentMonitorDTO;
import com.joker.demo.core.domain.enums.JobRequestEnum;
import com.joker.demo.core.domain.enums.JobRunStatusEnum;
import com.joker.demo.core.scheduler.JobSchedulerHandlerService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 组合服务器处理器
 * 能够同时处理HTTP请求和自定义协议消息
 *
 * @author Joker
 * @since 2025-07-26
 */
@ChannelHandler.Sharable
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    private static final Logger log = LoggerFactory.getLogger(NettyServerHandler.class);

    private final JobSchedulerHandlerService jobSchedulerHandlerService;

    // 存储客户端连接
    private final Map<String, ChannelHandlerContext> clientConnections = new ConcurrentHashMap<>();
    private final Map<ChannelHandlerContext, String> registerKeyMap = new ConcurrentHashMap<>();


    public NettyServerHandler(JobSchedulerHandlerService jobSchedulerHandlerService) {
        this.jobSchedulerHandlerService = jobSchedulerHandlerService;
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String clientId = getClientId(ctx);
        log.info("【调度器】channelActive 连接：{}", clientId);
        // 存储客户端连接
        clientConnections.computeIfAbsent(clientId, k -> {
            log.warn("【调度器】客户端不存在：{}", clientId);
            return ctx;
        });
        super.channelActive(ctx);
    }

    private String getClientId(ChannelHandlerContext ctx) {
        InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = remoteAddress.getAddress().getHostAddress();
        int clientPort = remoteAddress.getPort();
        return clientIp + ":" + clientPort;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            log.info("【调度器】收到自定义协议消息：{}", msg);

            // 解析消息
            MessageDTO request = JSON.parseObject(msg.toString(), MessageDTO.class);

            JobRequestEnum byCode = JobRequestEnum.getByCode(request.getType());
            if (byCode == null) {
                log.warn("未知消息类型：{}", request.getType());
                return;
            }

            // 处理不同类型的消息
            switch (byCode) {
                case REGISTER:
                    handleRegister(ctx, request);
                    break;
                case HEARTBEAT:
                    handleHeartbeat(ctx, request);
                    break;
                case EXECUTE_TASK_RESPONSE:
                    handleExecuteTaskResponse(ctx, request);
                    break;
                case TASK_RESULT:
                    handleTaskResult(ctx, request);
                    break;
                case CANCEL_TASK_RESPONSE:
                    handleCancelTaskResponse(ctx, request);
                    break;
                case THREAD_POOL_MONITOR:
                    handleThreadPoolMonitor(ctx, request);
                    break;
                case ENVIRONMENT_MONITOR:
                    handleEnvironmentMonitor(ctx, request);
                    break;
                default:
                    log.warn("未知消息类型：{}", request.getType());
            }

        } catch (Exception e) {
            log.error("处理自定义协议消息异常", e);
        }
    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 移除客户端连接
        String clientId = getClientId(ctx);
        log.info("【调度器】 有客户端 断开连接：{}", clientId);
        if (clientConnections.containsKey(clientId)) {
            clientConnections.remove(clientId);
            String registerKey = registerKeyMap.get(ctx);
            // 下线对应的该客户端注册的所有执行器
            Boolean b = jobSchedulerHandlerService.unregisterJobHandlers(registerKey);
            log.info("【调度器】下线执行器成功与否：{}", b);
        }
        super.channelInactive(ctx);
    }

    /**
     * 通过registerKey发送消息到执行器
     *
     * @param registerKey 执行器注册标识
     * @param message     要发送的消息
     * @return 是否发送成功
     */
    public boolean sendMessageToExecutor(String registerKey, MessageDTO message) {
        try {
            // 通过registerKey找到对应的ChannelHandlerContext
            ChannelHandlerContext targetCtx = null;
            for (Map.Entry<ChannelHandlerContext, String> entry : registerKeyMap.entrySet()) {
                if (registerKey.equals(entry.getValue())) {
                    targetCtx = entry.getKey();
                    break;
                }
            }

            if (targetCtx == null) {
                log.warn("未找到registerKey对应的执行器连接：{}", registerKey);
                return false;
            }

            // 检查连接是否活跃
            if (!targetCtx.channel().isActive()) {
                log.warn("执行器连接已断开：{}", registerKey);
                return false;
            }

            // 发送消息
            targetCtx.writeAndFlush(JSON.toJSONString(message));
            log.info("成功发送消息到执行器：{}，消息类型：{}", registerKey, message.getType());
            return true;

        } catch (Exception e) {
            log.error("发送消息到执行器失败：{}，错误：{}", registerKey, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 处理注册消息
     */
    private void handleRegister(ChannelHandlerContext ctx, MessageDTO request) {
        log.info("处理注册消息：{}", request.getContent());
        JobRegistryBO jobRegistryBO = JSON.parseObject(request.getContent(), JobRegistryBO.class);
        // 这里根据ctx 获取注册信息，设置registerKey
        String realRegisterKey = getClientId(ctx);
        log.error("【调度器】realRegisterKey：{}", realRegisterKey);
        jobRegistryBO.setRegisterKey(realRegisterKey);
        // 解析注册请求
        Boolean b = jobSchedulerHandlerService.registerJobHandlers(jobRegistryBO);
        log.info("【调度器】注册结果：{}", b);
        // 存储注册信息
        registerKeyMap.put(ctx, jobRegistryBO.getRegisterKey());
        // 发送注册响应
        MessageDTO response = new MessageDTO(JobRequestEnum.REGISTER_RESPONSE.getCode(), request.getMessageId(), "注册成功");
        ctx.writeAndFlush(JSON.toJSONString(response));
    }
    /**
     * 处理心跳消息
     */
    private void handleHeartbeat(ChannelHandlerContext ctx, MessageDTO request) {
        log.info("【调度器】处理心跳消息：{}", request.getContent());
        // 发送心跳响应
        MessageDTO response = new MessageDTO(JobRequestEnum.HEARTBEAT_RESPONSE.getCode(), request.getMessageId(), "心跳正常");
        ctx.writeAndFlush(JSON.toJSONString(response));
    }

    /**
     * 处理任务执行响应消息
     * 调度器接收到EXECUTE_TASK_RESPONSE 请求，将任务变成 运行中
     */
    private void handleExecuteTaskResponse(ChannelHandlerContext ctx, MessageDTO request) {
        log.info("【调度器】处理任务执行响应消息：{}", request.getContent());

        try {
            // 解析任务执行响应
            TaskExecuteResponseDTO taskResponse = JSON.parseObject(request.getContent(), TaskExecuteResponseDTO.class);

            // 调用调度器服务处理任务执行响应
            jobSchedulerHandlerService.execute(taskResponse);

            // 发送确认响应
            MessageDTO response = new MessageDTO(JobRequestEnum.TASK_RESULT_RESPONSE.getCode(), request.getMessageId(), "任务执行响应已接收");
            ctx.writeAndFlush(JSON.toJSONString(response));

        } catch (Exception e) {
            log.error("处理任务执行响应异常", e);
        }
    }

    /**
     * 处理任务结果消息
     * 执行器发送TASK_RESULT请求，将任务变成3种状态（运行失败/运行成功/运行超时）
     */
    private void handleTaskResult(ChannelHandlerContext ctx, MessageDTO request) {
        log.info("【调度器】处理任务结果消息：{}", request.getContent());

        try {
            // 解析任务结果
            TaskExecuteResponseDTO taskResult = JSON.parseObject(request.getContent(), TaskExecuteResponseDTO.class);

            // 调用调度器服务处理任务结果
            jobSchedulerHandlerService.receiveExecuteTaskResponse(taskResult);

            // 发送任务结果响应
            MessageDTO response = new MessageDTO(JobRequestEnum.TASK_RESULT_RESPONSE.getCode(), request.getMessageId(), "任务结果已接收");
            ctx.writeAndFlush(JSON.toJSONString(response));

        } catch (Exception e) {
            log.error("处理任务结果异常", e);
        }
    }

    /**
     * 处理任务取消响应消息
     * 调度器接收到 CANCEL_TASK_RESPONSE请求，将任务变成取消成功
     */
    private void handleCancelTaskResponse(ChannelHandlerContext ctx, MessageDTO request) {
        log.info("【调度器】处理任务取消响应消息：{}", request.getContent());

        try {
            // 解析任务取消响应
            TaskCancelResponseDTO cancelResponse = JSON.parseObject(request.getContent(), TaskCancelResponseDTO.class);

            // 调用调度器服务处理任务取消响应
            TaskExecuteResponseDTO taskResponse = new TaskExecuteResponseDTO();
            taskResponse.setJobLogId(cancelResponse.getJobLogId());
            taskResponse.setStatus(JobRunStatusEnum.CANCELED.getCode());
            taskResponse.setResult(cancelResponse.getMessage());

            jobSchedulerHandlerService.cancel(taskResponse);

            // 发送确认响应
            MessageDTO response = new MessageDTO(JobRequestEnum.TASK_RESULT_RESPONSE.getCode(), request.getMessageId(), "任务取消响应已接收");
            ctx.writeAndFlush(JSON.toJSONString(response));

        } catch (Exception e) {
            log.error("处理任务取消响应异常", e);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("组合服务器处理器异常", cause);
        ctx.close();
    }

    /**
     * 处理线程池监控数据
     * 接收执行器发送的线程池监控数据，进行解析和处理
     */
    private void handleThreadPoolMonitor(ChannelHandlerContext ctx, MessageDTO request) {
        log.info("【调度器】收到线程池监控数据，消息ID：{}", request.getMessageId());

        try {
            // 1. 解析监控数据
            ThreadPoolMonitorDTO monitorData = parseMonitorData(request);
            if (monitorData == null) {
                sendErrorResponse(ctx, request, "监控数据解析失败");
                return;
            }

            String registerKey = getClientId(ctx);
            monitorData.setRegisterKey(registerKey);

            // 2. 处理监控数据（存储到数据库、发送告警等）
            processThreadPoolMonitorData(monitorData);

            // 3. 发送成功响应
            sendSuccessResponse(ctx, request);

        } catch (Exception e) {
            log.error("【调度器】处理线程池监控数据失败，消息ID：{}，错误：{}",
                    request.getMessageId(), e.getMessage(), e);
            // 发送错误响应
            sendErrorResponse(ctx, request, "监控数据处理失败: " + e.getMessage());
        }
    }

    /**
     * 解析监控数据
     *
     * @param request 消息请求
     * @return 监控数据对象，解析失败返回null
     */
    private ThreadPoolMonitorDTO parseMonitorData(MessageDTO request) {
        try {
            if (StringUtils.isBlank(request.getContent())) {
                log.warn("【调度器】监控数据内容为空，消息ID：{}", request.getMessageId());
                return null;
            }

            ThreadPoolMonitorDTO monitorData = JSON.parseObject(request.getContent(), ThreadPoolMonitorDTO.class);
            if (monitorData == null) {
                log.warn("【调度器】监控数据解析失败，消息ID：{}，内容：{}",
                        request.getMessageId(), request.getContent());
                return null;
            }

            log.debug("【调度器】监控数据解析成功，执行器：{}，应用：{}",
                    monitorData.getRegisterKey(), monitorData.getAppName());
            return monitorData;

        } catch (Exception e) {
            log.error("【调度器】监控数据解析异常，消息ID：{}，错误：{}",
                    request.getMessageId(), e.getMessage(), e);
            return null;
        }
    }

    /**
     * 发送成功响应
     *
     * @param ctx     通道上下文
     * @param request 原始请求
     */
    private void sendSuccessResponse(ChannelHandlerContext ctx, MessageDTO request) {
        try {
            MessageDTO response = new MessageDTO(
                    JobRequestEnum.THREAD_POOL_MONITOR_RESPONSE.getCode(),
                    request.getMessageId(),
                    "监控数据已收到并处理成功");
            ctx.writeAndFlush(JSON.toJSONString(response));
            log.debug("【调度器】发送监控数据成功响应，消息ID：{}", request.getMessageId());
        } catch (Exception e) {
            log.error("【调度器】发送成功响应失败，消息ID：{}，错误：{}",
                    request.getMessageId(), e.getMessage(), e);
        }
    }

    /**
     * 发送错误响应
     *
     * @param ctx          通道上下文
     * @param request      原始请求
     * @param errorMessage 错误信息
     */
    private void sendErrorResponse(ChannelHandlerContext ctx, MessageDTO request, String errorMessage) {
        try {
            MessageDTO response = new MessageDTO(
                    JobRequestEnum.THREAD_POOL_MONITOR_RESPONSE.getCode(),
                    request.getMessageId(),
                    errorMessage);
            ctx.writeAndFlush(JSON.toJSONString(response));
            log.warn("【调度器】发送监控数据错误响应，消息ID：{}，错误：{}",
                    request.getMessageId(), errorMessage);
        } catch (Exception e) {
            log.error("【调度器】发送错误响应失败，消息ID：{}，错误：{}",
                    request.getMessageId(), e.getMessage(), e);
        }
    }

    /**
     * 处理线程池监控数据
     * 调用JobSchedulerHandlerService处理监控数据，包括数据库存储和状态更新
     */
    private void processThreadPoolMonitorData(ThreadPoolMonitorDTO monitorData) {
        try {
            // 调用JobSchedulerHandlerService处理监控数据
            jobSchedulerHandlerService.processThreadPoolMonitorData(monitorData);

            // 记录详细的监控数据日志
            logMonitorDataDetails(monitorData);

        } catch (Exception e) {
            log.error("【调度器】处理线程池监控数据失败，执行器：{}，错误：{}",
                    monitorData.getRegisterKey(), e.getMessage(), e);
        }
    }

    /**
     * 记录监控数据详细信息
     *
     * @param monitorData 监控数据
     */
    private void logMonitorDataDetails(ThreadPoolMonitorDTO monitorData) {
        log.info("【调度器】处理线程池监控数据 - 执行器: {}, 应用: {}, 时间: {}",
                monitorData.getRegisterKey(),
                monitorData.getAppName(),
                new java.util.Date(monitorData.getTimestamp()));

        // 记录线程池基本信息
        logThreadPoolInfo(monitorData);

        // 记录内存使用信息
        logMemoryInfo(monitorData);

        // 记录任务执行统计
        logTaskStatistics(monitorData);

        // 记录线程堆栈信息
        logThreadStackInfo(monitorData);
    }

    /**
     * 记录线程池信息
     *
     * @param monitorData 监控数据
     */
    private void logThreadPoolInfo(ThreadPoolMonitorDTO monitorData) {
        if (monitorData.getThreadPoolInfo() != null) {
            ThreadPoolMonitorDTO.ThreadPoolInfo info = monitorData.getThreadPoolInfo();
            log.info("【线程池状态】执行器：{} - 活跃线程: {}/{}, 队列大小: {}/{}, 已完成任务: {}",
                    monitorData.getRegisterKey(),
                    info.getActiveCount(), info.getPoolSize(),
                    info.getQueueSize(), info.getQueueSize() + info.getQueueRemainingCapacity(),
                    info.getCompletedTaskCount());
        }
    }

    /**
     * 记录内存使用信息
     *
     * @param monitorData 监控数据
     */
    private void logMemoryInfo(ThreadPoolMonitorDTO monitorData) {
        if (monitorData.getMemoryInfo() != null) {
            ThreadPoolMonitorDTO.MemoryInfo memory = monitorData.getMemoryInfo();
            log.info("【内存使用】执行器：{} - 已使用: {}MB/{}MB ({}%), 空闲: {}MB",
                    monitorData.getRegisterKey(),
                    memory.getUsedMemoryMB(), memory.getTotalMemoryMB(),
                    String.format("%.1f", memory.getMemoryUsagePercent()),
                    memory.getFreeMemoryMB());
        }
    }

    /**
     * 记录任务执行统计
     *
     * @param monitorData 监控数据
     */
    private void logTaskStatistics(ThreadPoolMonitorDTO monitorData) {
        if (monitorData.getTaskStatistics() != null) {
            ThreadPoolMonitorDTO.TaskStatistics stats = monitorData.getTaskStatistics();
            log.info("【任务统计】执行器：{} - 运行中: {}, 延迟: {}, 完成/分钟: {}, 失败/分钟: {}, 平均执行时间: {}ms",
                    monitorData.getRegisterKey(),
                    stats.getRunningTaskCount(), stats.getDelayTaskCount(),
                    stats.getCompletedTasksLastMinute(), stats.getFailedTasksLastMinute(),
                    String.format("%.1f", stats.getAverageTaskExecutionTimeMs()));
        }
    }

    /**
     * 记录线程堆栈信息
     *
     * @param monitorData 监控数据
     */
    private void logThreadStackInfo(ThreadPoolMonitorDTO monitorData) {
        if (monitorData.getThreadStackInfos() != null && !monitorData.getThreadStackInfos().isEmpty()) {
            log.info("【线程堆栈】执行器：{} - 共 {} 个活跃线程",
                    monitorData.getRegisterKey(), monitorData.getThreadStackInfos().size());

            // 只记录前5个线程的详细信息，避免日志过多
            int logCount = Math.min(5, monitorData.getThreadStackInfos().size());
            for (int i = 0; i < logCount; i++) {
                ThreadPoolMonitorDTO.ThreadStackInfo threadInfo = monitorData.getThreadStackInfos().get(i);
                log.info("【线程详情】执行器：{} - 线程 {} (ID: {}) - 状态: {}, 当前任务: {}",
                        monitorData.getRegisterKey(),
                        threadInfo.getThreadName(), threadInfo.getThreadId(),
                        threadInfo.getThreadState(), threadInfo.getCurrentTask());
            }

            // 如果有更多线程，只记录数量
            if (monitorData.getThreadStackInfos().size() > 5) {
                log.info("【线程堆栈】执行器：{} - 还有 {} 个线程未显示",
                        monitorData.getRegisterKey(),
                        monitorData.getThreadStackInfos().size() - 5);
            }
        }
    }

    /**
     * 处理环境监控数据
     * 接收执行器发送的环境监控数据，进行解析和处理
     */
    private void handleEnvironmentMonitor(ChannelHandlerContext ctx, MessageDTO request) {
        log.info("【调度器】收到环境监控数据，消息ID：{}", request.getMessageId());

        try {
            // 1. 解析监控数据
            EnvironmentMonitorDTO monitorData = parseEnvironmentMonitorData(request);
            if (monitorData == null) {
                sendEnvironmentErrorResponse(ctx, request, "环境监控数据解析失败");
                return;
            }
            // 获取真实注册键
            String registerKey = getClientId(ctx);
            monitorData.setRegisterKey(registerKey);

            // 2. 处理监控数据（存储到数据库、发送告警等）
            processEnvironmentMonitorData(monitorData);

            // 3. 发送成功响应
            sendEnvironmentSuccessResponse(ctx, request);

        } catch (Exception e) {
            log.error("【调度器】处理环境监控数据失败，消息ID：{}，错误：{}",
                    request.getMessageId(), e.getMessage(), e);
            // 发送错误响应
            sendEnvironmentErrorResponse(ctx, request, "环境监控数据处理失败: " + e.getMessage());
        }
    }

    /**
     * 解析环境监控数据
     *
     * @param request 消息请求
     * @return 环境监控数据对象，解析失败返回null
     */
    private EnvironmentMonitorDTO parseEnvironmentMonitorData(MessageDTO request) {
        try {
            if (StringUtils.isBlank(request.getContent())) {
                log.warn("【调度器】环境监控数据内容为空，消息ID：{}", request.getMessageId());
                return null;
            }

            EnvironmentMonitorDTO monitorData = JSON.parseObject(request.getContent(), EnvironmentMonitorDTO.class);
            if (monitorData == null) {
                log.warn("【调度器】环境监控数据解析失败，消息ID：{}，内容：{}",
                        request.getMessageId(), request.getContent());
                return null;
            }

            log.debug("【调度器】环境监控数据解析成功，执行器：{}，应用：{}",
                    monitorData.getRegisterKey(), monitorData.getAppName());
            return monitorData;

        } catch (Exception e) {
            log.error("【调度器】环境监控数据解析异常，消息ID：{}，错误：{}",
                    request.getMessageId(), e.getMessage(), e);
            return null;
        }
    }

    /**
     * 发送环境监控成功响应
     *
     * @param ctx     通道上下文
     * @param request 原始请求
     */
    private void sendEnvironmentSuccessResponse(ChannelHandlerContext ctx, MessageDTO request) {
        try {
            MessageDTO response = new MessageDTO(
                    JobRequestEnum.ENVIRONMENT_MONITOR_RESPONSE.getCode(),
                    request.getMessageId(),
                    "环境监控数据已收到并处理成功");
            ctx.writeAndFlush(JSON.toJSONString(response));
            log.debug("【调度器】发送环境监控数据成功响应，消息ID：{}", request.getMessageId());
        } catch (Exception e) {
            log.error("【调度器】发送环境监控成功响应失败，消息ID：{}，错误：{}",
                    request.getMessageId(), e.getMessage(), e);
        }
    }

    /**
     * 发送环境监控错误响应
     *
     * @param ctx          通道上下文
     * @param request      原始请求
     * @param errorMessage 错误信息
     */
    private void sendEnvironmentErrorResponse(ChannelHandlerContext ctx, MessageDTO request, String errorMessage) {
        try {
            MessageDTO response = new MessageDTO(
                    JobRequestEnum.ENVIRONMENT_MONITOR_RESPONSE.getCode(),
                    request.getMessageId(),
                    errorMessage);
            ctx.writeAndFlush(JSON.toJSONString(response));
            log.warn("【调度器】发送环境监控数据错误响应，消息ID：{}，错误：{}",
                    request.getMessageId(), errorMessage);
        } catch (Exception e) {
            log.error("【调度器】发送环境监控错误响应失败，消息ID：{}，错误：{}",
                    request.getMessageId(), e.getMessage(), e);
        }
    }

    /**
     * 处理环境监控数据
     * 调用JobSchedulerHandlerService处理环境监控数据，包括数据库存储和状态更新
     */
    private void processEnvironmentMonitorData(EnvironmentMonitorDTO monitorData) {
        try {
            // 调用JobSchedulerHandlerService处理环境监控数据
            jobSchedulerHandlerService.processEnvironmentMonitorData(monitorData);

            // 记录详细的环境监控数据日志
            logEnvironmentMonitorDataDetails(monitorData);

        } catch (Exception e) {
            log.error("【调度器】处理环境监控数据失败，执行器：{}，错误：{}",
                    monitorData.getRegisterKey(), e.getMessage(), e);
        }
    }

    /**
     * 记录环境监控数据详细信息
     *
     * @param monitorData 环境监控数据
     */
    private void logEnvironmentMonitorDataDetails(EnvironmentMonitorDTO monitorData) {
        log.info("【调度器】处理环境监控数据 - 执行器: {}, 应用: {}, 时间: {}",
                monitorData.getRegisterKey(),
                monitorData.getAppName(),
                new java.util.Date(monitorData.getTimestamp()));

        // 记录系统信息
        logSystemInfo(monitorData);

        // 记录JVM信息
        logJvmInfo(monitorData);

        // 记录磁盘信息
        logDiskInfo(monitorData);

        // 记录网络信息
        logNetworkInfo(monitorData);

        // 记录进程信息
        logProcessInfo(monitorData);
    }

    /**
     * 记录系统信息
     *
     * @param monitorData 环境监控数据
     */
    private void logSystemInfo(EnvironmentMonitorDTO monitorData) {
        if (monitorData.getSystemInfo() != null) {
            EnvironmentMonitorDTO.SystemInfo systemInfo = monitorData.getSystemInfo();
            log.info("【系统状态】执行器：{} - 操作系统: {} {}, CPU核心: {}, CPU使用率: {}%, 系统内存: {}MB/{}MB ({}%), 负载: {}",
                    monitorData.getRegisterKey(),
                    systemInfo.getOsName(), systemInfo.getOsVersion(),
                    systemInfo.getCpuCores(), systemInfo.getCpuUsagePercent(),
                    systemInfo.getUsedMemoryMB(), systemInfo.getTotalMemoryMB(),
                    systemInfo.getSystemMemoryUsagePercent(), systemInfo.getSystemLoadAverage());
        }
    }

    /**
     * 记录JVM信息
     *
     * @param monitorData 环境监控数据
     */
    private void logJvmInfo(EnvironmentMonitorDTO monitorData) {
        if (monitorData.getJvmInfo() != null) {
            EnvironmentMonitorDTO.JvmInfo jvmInfo = monitorData.getJvmInfo();
            log.info("【JVM状态】执行器：{} - JVM: {} {}, 堆内存: {}MB/{}MB ({}%), 线程数: {}/{}, 类加载: {}",
                    monitorData.getRegisterKey(),
                    jvmInfo.getJvmVendor(), jvmInfo.getJvmVersion(),
                    jvmInfo.getUsedHeapMemoryMB(), jvmInfo.getMaxHeapMemoryMB(),
                    jvmInfo.getHeapMemoryUsagePercent(), jvmInfo.getThreadCount(), jvmInfo.getPeakThreadCount(),
                    jvmInfo.getLoadedClassCount());
        }
    }

    /**
     * 记录磁盘信息
     *
     * @param monitorData 环境监控数据
     */
    private void logDiskInfo(EnvironmentMonitorDTO monitorData) {
        if (monitorData.getDiskInfos() != null && !monitorData.getDiskInfos().isEmpty()) {
            log.info("【磁盘状态】执行器：{} - 共 {} 个磁盘",
                    monitorData.getRegisterKey(), monitorData.getDiskInfos().size());

            // 只记录前3个磁盘的详细信息，避免日志过多
            int logCount = Math.min(3, monitorData.getDiskInfos().size());
            for (int i = 0; i < logCount; i++) {
                EnvironmentMonitorDTO.DiskInfo diskInfo = monitorData.getDiskInfos().get(i);
                log.info("【磁盘详情】执行器：{} - 磁盘 {} (路径: {}) - 使用率: {}%, 可用空间: {}MB/{}MB",
                        monitorData.getRegisterKey(),
                        diskInfo.getDiskName(), diskInfo.getDiskPath(),
                        diskInfo.getDiskUsagePercent(), diskInfo.getFreeSpaceMB(), diskInfo.getTotalSpaceMB());
            }

            // 如果有更多磁盘，只记录数量
            if (monitorData.getDiskInfos().size() > 3) {
                log.info("【磁盘状态】执行器：{} - 还有 {} 个磁盘未显示",
                        monitorData.getRegisterKey(),
                        monitorData.getDiskInfos().size() - 3);
            }
        }
    }

    /**
     * 记录网络信息
     *
     * @param monitorData 环境监控数据
     */
    private void logNetworkInfo(EnvironmentMonitorDTO monitorData) {
        if (monitorData.getNetworkInfo() != null && monitorData.getNetworkInfo().getNetworkInterfaces() != null) {
            log.info("【网络状态】执行器：{} - 总接收: {}MB, 总发送: {}MB",
                    monitorData.getRegisterKey(),
                    monitorData.getNetworkInfo().getTotalBytesReceived() / (1024 * 1024),
                    monitorData.getNetworkInfo().getTotalBytesSent() / (1024 * 1024));
        }
    }

    /**
     * 记录进程信息
     *
     * @param monitorData 环境监控数据
     */
    private void logProcessInfo(EnvironmentMonitorDTO monitorData) {
        if (monitorData.getProcessInfo() != null) {
            EnvironmentMonitorDTO.ProcessInfo processInfo = monitorData.getProcessInfo();
            log.info("【进程状态】执行器：{} - 进程ID: {}, 名称: {}, CPU使用率: {}%, 内存使用: {}MB, 线程数: {}",
                    monitorData.getRegisterKey(),
                    processInfo.getPid(), processInfo.getProcessName(),
                    processInfo.getProcessCpuUsagePercent(), processInfo.getProcessMemoryUsageMB(),
                    processInfo.getProcessThreadCount());
        }
    }
} 